package com.alnex.mongo.config;

import cn.hutool.core.util.StrUtil;
import com.alnex.mongo.res.UserRequest;
import com.alnex.mongo.utils.ReflectUtil;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author admin
 */
@Service
public class MongodbServiceImpl<T> implements MongodbService<T> {

    @Autowired
    MongoOperations mongoTemplate;
    @Autowired
    MongoTemplate mt;

    @Override
    public void update(T entity) {
        boolean flag = ReflectUtil.reflectObject(entity);
        if (!flag) {
            throw new NullPointerException("_id is null");
        }
        mongoTemplate.save(entity);
    }

    @Override
    public void saveOrUpdate(T entity) {
        mongoTemplate.save(entity);
    }

    @Override
    public void save(T entity) {
        mongoTemplate.insert(entity);
    }

    /**
     * 查询全部
     * 因为MongoDB具体要查询的document是设置在实体类的,所以需要传具体的实体类
     *
     * @author Alnex
     * @date 2021/5/31 11:19
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<T> findAll(T entity, UserRequest request) {
        Pageable pageable = PageRequest.of(request.currentPage(), request.currentSize());
        Query query = new Query();
        Criteria criteria = new Criteria();

        String name = request.getName();
        String age = request.getAge();
        String occupation = request.getOccupation();

        if (StrUtil.isNotBlank(name)){
            criteria.and("name").is(name);
        }
        if (StrUtil.isNotBlank(age)){
            criteria.and("age").is(age);
        }
        if (StrUtil.isNotBlank(occupation)){
            criteria.and("occupation").is(occupation);
        }
        query.addCriteria(criteria);
        query.with(pageable);

        // List<?> list = mongoTemplate.find(query, entity.getClass());
        List<?> list = mt.find(query, entity.getClass());
        return (List<T>) list;
    }

    /**
     * 查询全部
     * 因为MongoDB具体要查询的document是设置在实体类的,所以需要传具体的实体类
     *
     * @author Alnex
     * @date 2021/5/31 11:19
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<T> findAll(T entity) {
        List<?> list = mongoTemplate.findAll(entity.getClass());
        return (List<T>) list;
    }

    /**
     * @param id     编码</br>
     * @param entity 查询实体 </br>
     *               因为MongoDB具体要查询的document是设置在实体类的,所以需要传具体的实体类
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public T findById(String id, T entity) {
        Query queryById = new Query();
        queryById.addCriteria(Criteria.where("_id").is(new ObjectId(id)));
        return (T) mongoTemplate.findOne(queryById, entity.getClass());
    }

    /**
     * @param id     编码</br>
     * @param entity 查询实体</br>
     *               因为MongoDB具体要查询的document是设置在实体类的,所以需要传具体的实体类 </br>
     */
    @Override
    public void deleteById(String id, T entity) {
        mongoTemplate.remove(new Query(Criteria.where("_id").is(new ObjectId(id))), entity.getClass());
    }

    /**
     * @param id     编码</br>
     * @param key    键</br>
     * @param value  值</br>
     * @param entity 操作实体</br>
     *               因为MongoDB具体要查询的document是设置在实体类的,所以需要传具体的实体类 </br>
     */
    @Override
    public void updateById(String id, String key, Object value, T entity) {
        mongoTemplate.updateFirst(new Query(Criteria.where("_id").is(new ObjectId(id))), Update.update(key, value), entity.getClass());
    }
}
